# encoding: utf-8
from http import HTTPStatus

# import dashscope
import uuid
from TuGraphClient import TuGraphClient
from pydantic import BaseModel
import json
import httpx
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
from starlette.responses import JSONResponse

ESSENCE_PROMPT = "我会给你一段描述，是一段利用某一生物特性来进行创新的原理，现在需要你一步一步的思考，凝练这段话为一句15至20字左右的{" \
                 "本质}，本质描述的是利用某物得到某物，中间用——>连接。接下来我会给你一个例子，“减少霜冻的效果可以通过调整任何材料表面的纹理来实现，方法是添加毫米高的峰和谷，其间有小角度（40-60" \
                 "度），类似于薄荷叶表面的那些。波峰处的凝结增强，波谷处的凝结受到抑制。山谷中的少量凝结水随后蒸发，形成无霜区。即使在吸水的表面材料上，当低于冰点时，水仍然会从山谷中蒸发。这些表面可减少 60% " \
                 "的霜形成，理论上最多可减少 80%。尽管在表面地形的峰顶上仍然会形成一条细线霜，但可以用少得多的能量将其除霜。它还不需要使用具有较低霜点的液体或容易被划伤的表面涂层。”从这段话中可以得到[本质:{" \
                 "通过利用特殊的纹理——>形成无霜区}]。注意你的答复只包括中括号里的内容，即得到的本质，不需要输出思考过程。接下来我会给你描述，请你仔细思考"

ANALYSE_PROMPT = '''我会给你一段利用某一生物特性来进行创新的原理的描述，请基于这一生物特性的创新应用原理，你只需要关注这段话，凝练出一句分析。请直接给出一段话的分析，不超过25字，无需提供其他背景信息或解释。下面是一个例子。
描述："减少霜冻的效果可以通过调整任何材料表面的纹理来实现，方法是添加毫米高的峰和谷，其间有小角度（40-60度），类似于薄荷叶表面的那些。波峰处的凝结增强，波谷处的凝结受到抑制。山谷中的少量凝结水随后蒸发，形成无霜区。即使在吸水的表面材料上，当低于冰点时，水仍然会从山谷中蒸发。这些表面可减少 60% 的霜形成，理论上最多可减少 80%。尽管在表面地形的峰顶上仍然会形成一条细线霜，但可以用少得多的能量将其除霜。它还不需要使用具有较低霜点的液体或容易被划伤的表面涂层。"
输出：{通过特殊的纹理蒸发到达冰点的水。}
注意你的答复只包括中括号里的内容，即得到的分析，不需要输出思考过程'''

ECOLOGICAL_BEHAVIOR_PROMPT = '''以下一段描述生物策略的段落我现在需要你总结出这段描述中的生物主要活动或过程的关键词,
        比如跑、跳、吃、游泳、飞行、自我保护等。请提取主要行为或过程，只需要一个最重要的词来概括,严格遵守要求“不含其他任何文字和上下文”, 
        若有多种生物只需要留下一个核心生物的中文。例如：某段文字描述的是鸟的飞行行为,那么你应该输出的是：飞行。'''

ECOLOGICAL_PHENOMENON_PROMPT = '''你是一名专业的生物学家。以下是一段描述生物策略的段落，请阅读该生物策略的描述，总结出生物进行该行为的原理也即生态现象， 比如黏菌进行信息交流的生态现象是[
长出丝状网络传递物质和信息]，植物进行低温保护的生态现象是[通过纹理阻止霜的生成]。你只需要输出最核心的原理，除生态现象不要输出其他任何内容以及解释信息，并控制输出的生态原理不超过15字。'''

NAME_PROMPT = "我会给你一段话，请认真阅读并为该段话起一个名字，从名字中必须体现出挑战并能体现出该段话的内容，你只需要输出名字，不需要其他的解释信息，不超过8个字"

SUMMARY_PROMPT = "我会给你一段话，这段话是描述了一个挑战，请认真阅读该挑战并总结出挑战的解决办法，你只需要输出解决办法，不需要其他解释信息，不超过15个字"

BIO_COMPONENT_PROMPT = "请根据输入的生物策略内容，提取出起到核心作用的部分，大部分可能是器官，也可能是其他化学物质/生物特性/生态作用等。你只需要输出起到核心作用的部分，不需要任何西塔内容和解释信息"

# 大模型抽取接口
BASE_API_URL = "http://192.168.1.101:8034/v1/chat/completions"
# rag对话接口
# KNOWLEDGE_CHAT_URL = 'http://192.168.1.101:7861/chat/knowledge_base_chat'
KNOWLEDGE_CHAT_URL = 'http://192.168.1.101:7077/RAG'
# 向量搜索相关实体接口
VECTOR_SEARCH_URL = 'http://192.168.1.101:5007/KnowledgeConfirm'
# 链接预测接口
LINK_PREDICT_URL = 'http://192.168.1.101:7055/link_prediction'
# 知识确认自检接口
KNOWLEDGE_CONFIRM_URL = 'http://192.168.1.101:7044/self_check'
# 方案生成接口
SOLUTION_GENERATE_URL = 'http://192.168.1.101:4561/KnowledgeApplication'
client = httpx.AsyncClient()

app = FastAPI()


def get_graph_by_id(id: str):
    client = TuGraphClient("192.168.1.101:7070", "admin", "73@TuGraph")
    cypher = "MATCH (BioStrategy:BioKgBase_BioStrategy {id: '" + id + "'})\
    WITH BioStrategy\
    OPTIONAL MATCH (BioStrategy)-[:BioKgBase_BioStrategy__generateInnovation__BioKgBase_Innovation]-(Innovation:BioKgBase_Innovation)\
    WITH BioStrategy, Innovation\
    OPTIONAL MATCH (BioStrategy)-[:BioKgBase_BioStrategy__strategyBasedOn__BioKgBase_InnovationPrinciple]-(InnovationPrinciple:BioKgBase_InnovationPrinciple)\
    WITH BioStrategy, Innovation, InnovationPrinciple\
    OPTIONAL MATCH (BioStrategy)-[:BioKgBase_BioStrategy__haveFunction__BioKgBase_Function]-(Function:BioKgBase_Function)\
    WITH BioStrategy, Innovation, InnovationPrinciple, Function\
    OPTIONAL MATCH (BioStrategy)-[:BioKgBase_BioStrategy__sourceFrom__BioKgBase_BioComponent]-(BioComponent:BioKgBase_BioComponent)\
    WITH BioStrategy, Innovation, InnovationPrinciple, Function, BioComponent\
    OPTIONAL MATCH (BioStrategy)-[:BioKgBase_BioStrategy__havePotential__BioKgBase_ApplicationPotential]-(ApplicationPotential:BioKgBase_ApplicationPotential)\
    WITH BioStrategy, Innovation, InnovationPrinciple, Function, BioComponent, ApplicationPotential\
    OPTIONAL MATCH (Innovation)-[:BioKgBase_Innovation__solutionsTo__BioKgBase_Challenge]-(Challenge:BioKgBase_Challenge)\
    WITH BioStrategy, Innovation, InnovationPrinciple, Function, BioComponent, ApplicationPotential, Challenge\
    OPTIONAL MATCH (BioComponent)-[:BioKgBase_BioComponent__belongToBio__BioKgBase_BioEntity]-(BioEntity:BioKgBase_BioEntity)\
    WITH BioStrategy, Innovation, InnovationPrinciple, Function, BioComponent, ApplicationPotential, Challenge, BioEntity\
    OPTIONAL MATCH (BioEntity)-[:BioKgBase_BioEntity__belongTo__BioKgBase_BioTaxonomy]-(BioTaxonomy:BioKgBase_BioTaxonomy)\
    RETURN BioStrategy, Innovation, InnovationPrinciple, Function, BioComponent, ApplicationPotential, Challenge, BioEntity, BioTaxonomy"
    result = client.call_cypher(cypher)
    return result


# Utility function to handle external API requests
async def call_external_api(url: str, payload: dict):
    try:
        response = await client.post(url, json=payload, timeout=120)
        response.raise_for_status()
        return response.json()
    except httpx.RequestError as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.post('/api/graph/getGraphEntityAll')
def get_graph_entity_all():
    client = TuGraphClient("192.168.1.101:7070", "admin", "73@TuGraph")
    cypher = " MATCH (n) RETURN n LIMIT 100000"
    try:
        result = client.call_cypher(cypher)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    grouped_items = {}
    for sublist in result['result']:
        for item_str in sublist:
            if item_str == '"__null__"':
                continue
            item = json.loads(item_str)  # 解析JSON字符串为字典
            label = item['label']
            properties = item['properties']
            filtered_properties = {'label': label}  # 始终包含label

            # 根据不同的label选择不同的属性
            if label == "BioKgBase_BioStrategy":
                keys = ['id', 'name', 'description', 'author', 'source', 'addTime', 'updateTime',
                        'ecologicalBehavior', 'ecologicalPhenomenon']
            elif label == "BioKgBase_Innovation":
                keys = ['id', 'name', 'description', 'type', 'author', 'biologicalModel', 'applicationTechnology',
                        'essence']
            elif label == "BioKgBase_InnovationPrinciple":
                keys = ['id', 'description', 'analyse']
            elif label == "BioKgBase_Function":
                keys = ['id', 'name', 'description', 'shortName', 'enName']
            elif label == "BioKgBase_BioComponent":
                keys = ['id', 'name']
            elif label == "BioKgBase_ApplicationPotential":
                keys = ['id', 'application', 'effect']
            elif label == "BioKgBase_Challenge":
                keys = ['id', 'name', 'description', 'summary']
            elif label == "BioKgBase_BioEntity":
                keys = ['id', 'name', 'enName', 'description']
            elif label == "BioKgBase_Reference":
                keys = ['id', 'name', 'description', 'author', 'organization']
            elif label == "BioKgBase_MultimodalResource":
                keys = ['id', 'name', 'description', 'sourceUrl']
            elif label == "BioKgBase_TermDefine":
                keys = ['id', 'name', 'description', 'pronunciation']
            elif label == "BioKgBase_BioTaxonomy":
                keys = ['id', 'alias']
            elif label == "BioKgBase_TechnologyCategory":
                keys = ['id', 'alias']
            elif label == "BioKgBase_FunctionalHierarchy":
                keys = ['id', 'alias']
            elif label == "BioKgBase_TechnologyDomain":
                keys = ['id', 'alias']
            else:
                continue

            # 抽取指定的属性
            for key in keys:
                filtered_properties[key] = properties.get(key, None)

            # 根据label将item分类
            if label not in grouped_items:
                grouped_items[label] = []
            if filtered_properties not in grouped_items[label]:
                grouped_items[label].append(filtered_properties)

    return {"message": "ok", "count": sum([len(grouped_items[label]) for label in grouped_items.keys()]),
            "result": grouped_items}


@app.post('/api/graph/getGraphAllById')
async def get_graph_all_by_id(request: Request):
    data = await request.json()
    id = data.get('id', '')
    try:
        res = get_graph_by_id(id)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

    grouped_items = {}
    for sublist in res['result']:
        for item_str in sublist:
            if item_str == '"__null__"':
                continue
            item = json.loads(item_str)  # 解析JSON字符串为字典
            label = item['label']
            properties = item['properties']
            filtered_properties = {'label': label}  # 始终包含label

            # 根据不同的label选择不同的属性
            if label == "BioKgBase_BioStrategy":
                keys = ['id', 'name', 'description', 'author', 'source', 'addTime', 'updateTime',
                        'ecologicalBehavior', 'ecologicalPhenomenon']
            elif label == "BioKgBase_Innovation":
                keys = ['id', 'name', 'description', 'type', 'author', 'biologicalModel', 'applicationTechnology',
                        'essence']
            elif label == "BioKgBase_InnovationPrinciple":
                keys = ['id', 'description', 'analyse']
            elif label == "BioKgBase_Function":
                keys = ['id', 'name', 'description', 'shortName', 'enName']
            elif label == "BioKgBase_BioComponent":
                keys = ['id', 'name']
            elif label == "BioKgBase_ApplicationPotential":
                keys = ['id', 'application', 'effect']
            elif label == "BioKgBase_Challenge":
                keys = ['id', 'name', 'description', 'summary']
            elif label == "BioKgBase_BioEntity":
                keys = ['id', 'name', 'enName', 'description']
            elif label == "BioKgBase_BioTaxonomy":
                keys = ['id', 'name']
            else:
                continue

            # 抽取指定的属性
            for key in keys:
                filtered_properties[key] = properties.get(key, None)

            # 根据label将item分类
            if label not in grouped_items:
                grouped_items[label] = []
            if filtered_properties not in grouped_items[label]:
                grouped_items[label].append(filtered_properties)

    return {"message": "ok", "count": sum([len(grouped_items[label]) for label in grouped_items.keys()]),
            "result": grouped_items}


@app.post('/api/graph/getGraphById')
async def getGraphById(request: Request):
    data = await request.json()
    id = data.get('id', '')
    try:
        res = get_graph_by_id(id)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

    grouped_items = {}
    for sublist in res['result']:
        for item_str in sublist:
            if item_str == '"__null__"':
                continue
            item = json.loads(item_str)  # 解析JSON字符串为字典
            label = item['label']
            properties = item['properties']
            filtered_properties = {'label': label}  # 始终包含label

            # 根据不同的label选择不同的属性
            if label == "BioKgBase_BioStrategy":
                keys = ['id', 'name', 'description',
                        'ecologicalBehavior', 'ecologicalPhenomenon']
            elif label == "BioKgBase_Innovation":
                keys = ['id', 'name', 'description', 'essence']
            elif label == "BioKgBase_InnovationPrinciple":
                keys = ['id', 'description', 'analyse']
            elif label == "BioKgBase_Function":
                keys = ['id', 'name', 'description']
            elif label == "BioKgBase_BioComponent":
                keys = ['id', 'name']
            elif label == "BioKgBase_ApplicationPotential":
                keys = ['id', 'application']
            elif label == "BioKgBase_Challenge":
                keys = ['id', 'name', 'description', 'summary']
            elif label == "BioKgBase_BioEntity":
                keys = ['id', 'name']
            elif label == "BioKgBase_BioTaxonomy":
                keys = ['id', 'name']
            else:
                continue

            # 抽取指定的属性
            for key in keys:
                filtered_properties[key] = properties.get(key, None)

            # 根据label将item分类
            if label not in grouped_items:
                grouped_items[label] = []
            if filtered_properties not in grouped_items[label]:
                grouped_items[label].append(filtered_properties)

    return {"message": "ok", "count": sum([len(grouped_items[label]) for label in grouped_items.keys()]),
            "result": grouped_items}



if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=5005)
